import axios from 'axios'
import {ElLoading, ElMessage, ElMessageBox, ElNotification} from 'element-plus'
import errorCode from '@/utils/errorCode'
import {blobValidate, tansParams} from '@/utils/ruoyi'
import {saveAs} from 'file-saver'
import useUserStore from '@/store/modules/user'
import setHeaderToken from "@/utils/Request/setHeaderToken.js";
import setQueryParams from "@/utils/Request/setQueryParams.js";
import setPostRestrict from "@/utils/Request/setPostRestrict.js";
import setEncryptPost from "@/utils/Request/setEncryptPost.js";

let downloadLoadingInstance;
// 是否显示重新登录
export let isRelogin = {show: false};

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
    // axios中请求配置有baseURL选项，表示请求URL公共部分
    baseURL: import.meta.env.VITE_APP_BASE_API, // 超时
    timeout: 30000
})

// 请求装饰器
const requestDecorator = (config, decorator, ...args) => {
    return decorator(config, ...args);
}

// request拦截器
service.interceptors.request.use(config => {
    // 是否需要设置 token
    const isToken = (config.headers || {}).isToken === false
    // 是否需要防止数据重复提交
    const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
    // 是否需要对提交的数据进行加密
    const isEncrypt = config.isEncrypt ?? true;
    // 添加 header Token
    config = requestDecorator(config, setHeaderToken, isToken);
    // 优化 Get 请求映射 Params 参数
    config = requestDecorator(config, setQueryParams);
    // post 请求加密
    config = requestDecorator(config, setEncryptPost, isEncrypt)
    // post 限制
    config = requestDecorator(config, setPostRestrict, isRepeatSubmit);

    return config
}, error => {
    console.log(error)
    Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
    // 未设置状态码则默认成功状态
    const code = res.data.code || 200;
    // 获取错误信息
    const msg = errorCode[code] || res.data.msg || errorCode['default']
    // 二进制数据则直接返回
    if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
        return res.data
    }
    if (code === 401) {
        if (!isRelogin.show) {
            isRelogin.show = true;
            ElMessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', {
                confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning'
            }).then(() => {
                isRelogin.show = false;
                useUserStore().logOut().then(() => {
                    location.href = '/index';
                })
            }).catch(() => {
                isRelogin.show = false;
            });
        }
        return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
    } else if (code === 500) {
        ElMessage({message: msg, type: 'error'})
        return Promise.reject(new Error(msg))
    } else if (code === 601) {
        ElMessage({message: msg, type: 'warning'})
        return Promise.reject(new Error(msg))
    } else if (code !== 200) {
        ElNotification.error({title: msg})
        return Promise.reject('error')
    } else {
        return Promise.resolve(res.data)
    }
}, error => {
    console.log('err' + error)
    let {message} = error;
    if (message == "Network Error") {
        message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
        message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
        message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    ElMessage({message: message, type: 'error', duration: 5 * 1000})
    return Promise.reject(error)
})

// 通用下载方法
export function download(url, params, filename, config) {
    downloadLoadingInstance = ElLoading.service({text: "正在下载数据，请稍候", background: "rgba(0, 0, 0, 0.7)",})
    return service.post(url, params, {
        transformRequest: [(params) => {
            return tansParams(params)
        }], headers: {'Content-Type': 'application/x-www-form-urlencoded'}, responseType: 'blob', ...config
    }).then(async (data) => {
        const isBlob = blobValidate(data);
        if (isBlob) {
            const blob = new Blob([data])
            saveAs(blob, filename)
        } else {
            const resText = await data.text();
            const rspObj = JSON.parse(resText);
            const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
            ElMessage.error(errMsg);
        }
        downloadLoadingInstance.close();
    }).catch((r) => {
        console.error(r)
        ElMessage.error('下载文件出现错误，请联系管理员！')
        downloadLoadingInstance.close();
    })
}

export default service
